package auth

import (
	"SlowAdmin/models"
	"errors"
	"github.com/astaxie/beego"
	"github.com/beego/beego/v2/core/logs"
	"github.com/golang-jwt/jwt/v4"
	"github.com/spf13/cast"
	"strconv"
	"time"
)

type CustomClaims struct {
	models.AdminUser
	jwt.StandardClaims
}

var MySecret = cast.ToString(beego.AppConfig.String("app_key"))

// 创建 Token
func GenToken(user models.AdminUser) (string, error) {
	claim := CustomClaims{
		user,
		jwt.StandardClaims{
			ExpiresAt: time.Now().Add(time.Hour * 3).Unix(), //3小时后过期
			Issuer:    "slow",                                       //签发人
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
	return token.SignedString([]byte(MySecret))
}

// 解析 token
func ParseToken(tokenStr string) (*CustomClaims, error) {
	token, err := jwt.ParseWithClaims(tokenStr, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(MySecret), nil
	})
	if err != nil {
		logs.Error("token parse err:", err)
		return nil, err
	}
	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
		return claims, nil
	}
	return nil, errors.New("invalid token")
}

// 刷新 Token
func RefreshToken(tokenStr string) (string, error) {
	jwt.TimeFunc = func() time.Time {
		return time.Unix(0, 0)
	}

	token, err := jwt.ParseWithClaims(tokenStr, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(MySecret), nil
	})
	if err != nil {
		return "", err
	}
	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
		jwt.TimeFunc = time.Now
		claims.StandardClaims.ExpiresAt = time.Now().Add(time.Hour * 3).Unix()
		return GenToken(claims.AdminUser)
	}
	return "", errors.New("Cloudn't handle this token")
}

// @title 根据token获取用户信息
func GetUserByToken(token string) (models.AdminUser, error) {
	claims, err := ParseToken(token)

	if err != nil {
		return models.AdminUser{}, err
	}

	var user = models.AdminUser{}

	return user.GetOne(strconv.Itoa(int(claims.AdminUser.Id))), nil
}
